home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 15 code / Floating Windows / Infinity Windoid WDEF 3.0 / Source Code / WindoidUtil.c < prev    next >
Encoding:
Text File  |  1995-02-20  |  17.1 KB  |  566 lines  |  [TEXT/MMCC]

  1. // *****************************************************************************
  2. //
  3. //    WindoidUtil.c
  4. //
  5. // —————————————————————————————————————————————————————————————————————————————
  6. //    Copyright © 1991-95 Infinity Systems.  All rights reserved.
  7. // —————————————————————————————————————————————————————————————————————————————
  8. //    DESCRIPTION:
  9. //        This file contains utility routines that the Infinity Windoid
  10. //        WDEF uses in order to get its job done.
  11. // —————————————————————————————————————————————————————————————————————————————
  12. //    WRITTEN BY:
  13. //        Troy Gaul (tgaul@halcyon.com)
  14. //        Infinity Systems
  15. // *****************************************************************************
  16.  
  17. #include "WindoidUtil.h"
  18.  
  19. #include <GestaltEqu.h>
  20. #include <Memory.h>
  21.  
  22. #include "WindoidDraw.h"
  23. #include "WindoidTypes.h"
  24.  
  25.  
  26. // *****************************************************************************
  27. //
  28. //    Environment-determining Routines                                                                             
  29. //
  30. // —————————————————————————————————————————————————————————————————————————————
  31. //        These use SysEnvirons by default so we don’t have to rely on Gestalt 
  32. //        being available and so MPW won’t include that code in our resource. 
  33. //        This can be changed by defining qUseGestalt to be 1.
  34. // *****************************************************************************
  35.  
  36. // —————————————————————————————————————————————————————————————————————————————
  37. //
  38. //    HasSystem7
  39. //
  40. // —————————————————————————————————————————————————————————————————————————————
  41. Boolean 
  42. HasSystem7()
  43. {
  44. #if qUseGestalt || SystemSevenOrLater
  45.     long vers = 0;
  46.     
  47.     return (Gestalt(gestaltSystemVersion, &vers) == noErr 
  48.             && ((vers & 0xFFFF) >= 0x0700));
  49. #else  
  50.     SysEnvRec theWorld;
  51.     
  52.     return (SysEnvirons(1, &theWorld) == noErr 
  53.             && theWorld.systemVersion >= 0x0700);
  54. #endif
  55. }
  56.  
  57.  
  58. // —————————————————————————————————————————————————————————————————————————————
  59. //
  60. //    HasCQDraw
  61. //
  62. // —————————————————————————————————————————————————————————————————————————————
  63. Boolean 
  64. HasCQDraw() 
  65. {
  66. #if qUseGestalt || SystemSevenOrLater
  67.      long vers = 0;
  68.     
  69.     return (Gestalt(gestaltQuickdrawVersion, &vers) == noErr 
  70.             && (vers & 0xFF00));
  71. #else
  72.     SysEnvRec theWorld;
  73.     
  74.     return ((SysEnvirons(1, &theWorld) == noErr) && 
  75.             theWorld.hasColorQD);
  76. #endif
  77. }
  78.  
  79.  
  80. // —————————————————————————————————————————————————————————————————————————————
  81. //
  82. //    SyncPorts
  83. //
  84. // —————————————————————————————————————————————————————————————————————————————
  85. //        Straight from the pages of _Macintosh Programming Secrets_, Second 
  86. //        Edition by Scott Knaster and Keith Rollin (page 425). (except that this
  87. //        version doesn’t check Gestalt, it will only be called if CQD is running)
  88. //        This routines was added to 2.3. It makes sure the drawing environment 
  89. //        is set correctly if the system has color. This is not needed for the 
  90. //        code in this WDEF as it is, but if a DoWDrawGIcon handler is implemented, 
  91. //        this is needed to make sure the drawing environment is set as Apple 
  92. //        tells us it will be for drawing the gray, xor’ed border.
  93. // —————————————————————————————————————————————————————————————————————————————
  94. void 
  95. SyncPorts() 
  96. {
  97.     GrafPtr bwPort;
  98.     CGrafPtr colorPort;
  99.     
  100.     GetWMgrPort(&bwPort);
  101.     GetCWMgrPort(&colorPort);
  102.     SetPort((GrafPtr) colorPort);
  103.     
  104.     BlockMoveData(&bwPort->pnLoc, &colorPort->pnLoc, 10);
  105.     BlockMoveData(&bwPort->pnVis, &colorPort->pnVis, 14);
  106.     PenPat((ConstPatternParam) &bwPort->pnPat);
  107.     BackPat((ConstPatternParam) &bwPort->bkPat);
  108. }
  109.  
  110.  
  111. // —————————————————————————————————————————————————————————————————————————————
  112. //
  113. //    OurDeviceLoop
  114. //
  115. // —————————————————————————————————————————————————————————————————————————————
  116. //        Under System 7, calls through to the System’s DeviceLoop, on Systems
  117. //        earlier than that, simulates the same behavior (perhaps a little more
  118. //        inefficiently, however, since I don’t group similar devices).
  119. // —————————————————————————————————————————————————————————————————————————————
  120. #if !SystemSevenOrLater
  121.  
  122. void 
  123. OurDeviceLoop(RgnHandle drawingRgn, DeviceLoopDrawingUPP drawingProc,
  124.               long userData, DeviceLoopFlags flags)
  125. {
  126.     if (HasSystem7())
  127.         DeviceLoop(drawingRgn, drawingProc, userData, flags);
  128.             // This works with or without Color Quickdraw.
  129.             
  130.     else
  131.         CallDeviceLoopDrawingProc(drawingProc, 1, 0, nil, userData);
  132.             // We used to emulate a DeviceLoop using Device Manager calls,  
  133.             // but since System 6 coloring of the WDEF was dropped, we can   
  134.             // skip all that and call just the drawing routine directly.
  135. }
  136.  
  137.  
  138. #endif
  139. // *****************************************************************************
  140. //
  141. //    Color Mixing Routines                                                                     
  142. //
  143. // *****************************************************************************
  144.  
  145. // —————————————————————————————————————————————————————————————————————————————
  146. //
  147. //    UseDefaultColor
  148. //
  149. // —————————————————————————————————————————————————————————————————————————————
  150. //        This routine will return some defaults in case neither the window’s 
  151. //        color table nor the System’s is long enough to contain the color 
  152. //        requested.  It was provided by Jim Petrick as part of a fix for a bug 
  153. //        in version 2.3 of the Infinity Windoid. This problem would be seen if 
  154. //        a custom WCTB was being used which was not as long as the default 
  155. //        System one (or if the System one had been changed to a shorter size). 
  156. //        The rest of Jim’s fix can be found in GetWctbColor.
  157. // —————————————————————————————————————————————————————————————————————————————
  158. static void 
  159. UseDefaultColor(short index, RGBColor *theColor) 
  160. {
  161.     switch (index) {
  162.         case wContentColor:            //     0
  163.         case wTitleBarColor:        //     4
  164.         case wHiliteColorLight:        //     5
  165.         case wTitleBarLight:        //     7
  166.             theColor->red = theColor->green = theColor->blue = 0xFFFF;
  167.             break;
  168.                 
  169.         case wDialogLight:            //     9
  170.         case wTingeLight:            //    11
  171.             theColor->red = theColor->green = 0xCCCC;
  172.             theColor->blue = 0xFFFF;
  173.             break;
  174.         
  175.         case wTingeDark:            //    12
  176.             theColor->red = theColor->green = 0x3333;
  177.             theColor->blue = 0x6666;
  178.             break;
  179.  
  180.         default:
  181.             theColor->red = theColor->green = theColor->blue = 0;
  182.             break;
  183.     }
  184. }
  185.  
  186.  
  187. // —————————————————————————————————————————————————————————————————————————————
  188. //
  189. //    GetWctbColor
  190. //
  191. // —————————————————————————————————————————————————————————————————————————————
  192. //        Given a partCode, return the RGBColor associated with it. (Using the
  193. //        default window color table.)
  194. // —————————————————————————————————————————————————————————————————————————————
  195. static void 
  196. GetWctbColor(WindowPeek window, short partCode, RGBColor *theColor) 
  197. {
  198.     AuxWinHandle awHndl;
  199.     short count;
  200.     
  201.     // Get the Color table for the window if it has one.
  202.     (void) GetAuxWin((WindowPtr) window, &awHndl); 
  203.     count = (**(WCTabHandle) (**awHndl).awCTable).ctSize;
  204.     
  205.     // If the table didn’t contain the entry of interest, look to the 
  206.     // default table.
  207.     if (count < partCode) {
  208.         (void) GetAuxWin(nil, &awHndl); 
  209.         count = (**(WCTabHandle) (**awHndl).awCTable).ctSize;
  210.     }
  211.     
  212.     // If the entry is there, use it, if not make a best guess at a default value.
  213.     if (count < partCode)
  214.         UseDefaultColor(partCode, theColor);
  215.     else
  216.         *theColor = (**(WCTabHandle) (**awHndl).awCTable).ctTable[partCode].rgb;
  217. }
  218.  
  219.  
  220. // —————————————————————————————————————————————————————————————————————————————
  221. //
  222. //    WctbForeColor
  223. //
  224. // —————————————————————————————————————————————————————————————————————————————
  225. void 
  226. WctbForeColor(WindowPeek window, short partCode) 
  227. {
  228.     RGBColor theColor;
  229.  
  230.     GetWctbColor(window, partCode, &theColor);
  231.     RGBForeColor(&theColor);
  232. }
  233.  
  234.  
  235. // —————————————————————————————————————————————————————————————————————————————
  236. //
  237. //    WctbBackColor
  238. //
  239. // —————————————————————————————————————————————————————————————————————————————
  240. void
  241. WctbBackColor(WindowPeek window, short partCode) 
  242. {
  243.     RGBColor theColor;
  244.  
  245.     GetWctbColor(window, partCode, &theColor);
  246.     RGBBackColor(&theColor);
  247. }
  248.  
  249.  
  250. // —————————————————————————————————————————————————————————————————————————————
  251. //
  252. //    MixColor
  253. //
  254. // —————————————————————————————————————————————————————————————————————————————
  255. //        Note: MixColor uses pragma processor 68020 to reduce code size with 
  256. //        MPW.  This is okay because MixColor will only be called if we are
  257. //        doing System 7 color, which requires Color Quickdraw, which is only
  258. //        available on systems with 68020’s or better.  If it isn’t compiled this 
  259. //        way, several glue routines will be added to the code WDEF resource to 
  260. //        handle the long integer arithmetic.
  261. // —————————————————————————————————————————————————————————————————————————————
  262. #pragma processor 68020
  263.  
  264. static void 
  265. MixColor(const RGBColor *light, const RGBColor *dark, short shade, 
  266.          RGBColor *result) 
  267. {
  268.     shade = 0x0F - shade;
  269.         // This is necessary because we give shades between light and
  270.         // dark (0% is light), but for colors, $0000 is black and $FFFF 
  271.         // is dark.
  272.  
  273.     result->red      = (long) (light->red   - dark->red)   * shade / 15 + dark->red;
  274.     result->green = (long) (light->green - dark->green) * shade / 15 + dark->green;
  275.     result->blue  = (long) (light->blue  - dark->blue)  * shade / 15 + dark->blue;
  276. }
  277.  
  278.  
  279. #pragma processor 68000
  280. // —————————————————————————————————————————————————————————————————————————————
  281. //
  282. //    AvgWctbColor
  283. //
  284. // —————————————————————————————————————————————————————————————————————————————
  285. //        Mix two parts by the given shade, which is actually a value
  286. //        between 0 (0%) and 15 (100%), return the RGBColor.
  287. // —————————————————————————————————————————————————————————————————————————————
  288. static void 
  289. AvgWctbColor(WindowPeek window, short light, short dark, short shade, 
  290.              RGBColor *theColor) 
  291. {
  292.     RGBColor lightColor;
  293.     RGBColor darkColor;
  294.  
  295.     GetWctbColor(window, light, &lightColor);
  296.     GetWctbColor(window, dark, &darkColor);
  297.     MixColor(&lightColor, &darkColor, shade, theColor);
  298. }
  299.  
  300.  
  301. // —————————————————————————————————————————————————————————————————————————————
  302. //
  303. //    AvgWctbForeColor
  304. //
  305. // —————————————————————————————————————————————————————————————————————————————
  306. void 
  307. AvgWctbForeColor(WindowPeek window, short light, short dark, short shade) 
  308. {
  309.     RGBColor theColor;
  310.     
  311.     AvgWctbColor(window, light, dark, shade, &theColor);
  312.     RGBForeColor(&theColor);
  313. }
  314.  
  315.  
  316. // —————————————————————————————————————————————————————————————————————————————
  317. //
  318. //    AvgWctbBackColor
  319. //
  320. // —————————————————————————————————————————————————————————————————————————————
  321. void 
  322. AvgWctbBackColor(WindowPeek window, short light, short dark, short shade) 
  323. {
  324.     RGBColor theColor;
  325.     
  326.     AvgWctbColor(window, light, dark, shade, &theColor);
  327.     RGBBackColor(&theColor);
  328. }
  329.  
  330.  
  331. // *****************************************************************************
  332. //
  333. //    CheckDisplay -- Check to see if we are using color title bars
  334. //
  335. // *****************************************************************************
  336.  
  337. // —————————————————————————————————————————————————————————————————————————————
  338. //
  339. //    CheckAvailable
  340. //
  341. // —————————————————————————————————————————————————————————————————————————————
  342. //        Given a light and dark index value, a count, and and an array of
  343. //        ‘percentage’ values (0x0 to 0xF, or 0 to 15), see if each of the
  344. //        values in the ramp maps to a different color on the screen. If not,
  345. //        we need to use black-and-white.
  346. // —————————————————————————————————————————————————————————————————————————————
  347. static Boolean 
  348. CheckAvailable(WindowPeek window, short light, short dark, short count, 
  349.                short *ramp) 
  350. {
  351.     RGBColor theColor;
  352.     short i;
  353.     short colorIndex = 0;
  354.     short lastIndex;
  355.     
  356.     for (i = 0 ; i < count ; i++) {
  357.         AvgWctbColor(window, light, dark, ramp[i], &theColor);    
  358.         
  359.         lastIndex = colorIndex;
  360.         colorIndex = Color2Index(&theColor);
  361.         
  362.         if (i > 0 && colorIndex == lastIndex)    // return false if two entries
  363.             return false;                        // have the same index value
  364.     }
  365.     return true;
  366. }
  367.  
  368.  
  369. // —————————————————————————————————————————————————————————————————————————————
  370. //
  371. //    CheckDisplay
  372. //
  373. // —————————————————————————————————————————————————————————————————————————————
  374. //        This routine checks to see if the device in question is color, if
  375. //        System 7 is running, and if there are ‘enough’ colors to draw the 
  376. //        title bar in color under System 7.   This might not be the case if
  377. //        the application is using a custom window palette.
  378. //        
  379. //        It does so in the same way that Apple’s system WDEF does. I essentially 
  380. //        took the assembly code that Apple released and made this use the same
  381. //        algorithm.
  382. // —————————————————————————————————————————————————————————————————————————————
  383. Boolean 
  384. CheckDisplay(short theDepth, short deviceFlags, GDHandle targetDevice, 
  385.              WindowPeek window) 
  386. {
  387.     Boolean inColor;
  388.     Boolean use7Color = false;            // Assume Black and White.
  389.     
  390.     if (theDepth >= 4 && (**targetDevice).gdType != fixedType && HasSystem7()) {
  391.         // A passive matrix screen on a PowerBook is a fixed device type.
  392.         // This seems to be how the Apple WDEF determines when to use black
  393.         // and white on those displays.
  394.         
  395.         RGBColor testColor;
  396.         GetWctbColor(window, wTingeLight, &testColor);
  397.         
  398.         // Check for B&W control panel setting.
  399.         if (testColor.red != 0 || testColor.green != 0 || testColor.blue != 0) 
  400.             use7Color = true;            // System 7.0 Color.
  401.     }
  402.     // Note: Since I didn’t find another way to see if the user had changed
  403.     // the settings in the Color control panel to the Black-and-white setting,
  404.     // I actually check to see if the rgb components of the light tinge color
  405.     // are non-zero (which seemed to be the case with that setting). 
  406.     
  407.     // Check to see if there are ‘enough’ colors to draw in color.
  408.     inColor = HasCQDraw() && (deviceFlags & (0x0001 << gdDevType));
  409.     
  410.     if (use7Color && inColor && theDepth <= 8) {
  411.         GDHandle saveDevice = GetGDevice();
  412.         short ramp[5];
  413.             // Make this array big enough for the largest ramp.
  414.         
  415.         use7Color = false;
  416.         SetGDevice(targetDevice);
  417.  
  418.         ramp[0] = 0x00;
  419.         ramp[1] = 0x07;
  420.         ramp[2] = 0x08;
  421.         ramp[3] = 0x0A;
  422.         ramp[4] = 0x0D;
  423.         if (CheckAvailable(window, wHiliteColorLight, wHiliteColorDark, 5, ramp)) {
  424.             ramp[0] = 0x00;
  425.             ramp[1] = 0x01;
  426.             ramp[2] = 0x04;
  427.             if (CheckAvailable(window, wTitleBarLight, wTitleBarDark, 3, ramp)) {
  428.                 ramp[0] = 0x00;
  429.                 ramp[1] = 0x04;
  430.                 ramp[2] = 0x0F;
  431.                 if (CheckAvailable(window, wTingeLight, wTingeDark, 3, ramp))
  432.                     use7Color = true;
  433.             }
  434.         }
  435.         SetGDevice(saveDevice);
  436.     }
  437.     
  438.     return use7Color;
  439. }
  440.  
  441.  
  442. // *****************************************************************************
  443. //
  444. //    General Helper Functions
  445. //
  446. // *****************************************************************************
  447.  
  448. // —————————————————————————————————————————————————————————————————————————————
  449. //
  450. //    ColorsNormal
  451. //
  452. // —————————————————————————————————————————————————————————————————————————————
  453. void
  454. ColorsNormal() 
  455. {
  456.     ForeColor(blackColor);
  457.     BackColor(whiteColor);
  458. }
  459.  
  460.  
  461. // —————————————————————————————————————————————————————————————————————————————
  462. //
  463. //    MoveRectTo
  464. //
  465. // —————————————————————————————————————————————————————————————————————————————
  466. void
  467. MoveRectTo(Rect *theRect, short left, short top) 
  468. {
  469.     theRect->right    += left - theRect->left;
  470.     theRect->bottom    += top  - theRect->top;
  471.     theRect->left     = left;
  472.     theRect->top     = top;
  473. }
  474.  
  475.  
  476. // —————————————————————————————————————————————————————————————————————————————
  477. //
  478. //    FrameBox
  479. //
  480. // —————————————————————————————————————————————————————————————————————————————
  481. void 
  482. FrameBox(const Rect *theRect) 
  483. {
  484.     Rect tempRect = *theRect;
  485.     
  486.     FrameRect(theRect);
  487.     InsetRect(&tempRect, 1, 1);
  488.     EraseRect(&tempRect);
  489. }
  490.  
  491.  
  492. // —————————————————————————————————————————————————————————————————————————————
  493. //
  494. //    FrameTopLeftShading
  495. //
  496. // —————————————————————————————————————————————————————————————————————————————
  497. void
  498. FrameTopLeftShading(Rect theRect) 
  499. {
  500.     theRect.right--;        // Compensate for the way the rectangle hangs.
  501.     theRect.bottom--;
  502.  
  503.     MoveTo(theRect.left,  theRect.bottom);            //    •••••
  504.     LineTo(theRect.left,  theRect.top   );            //    •
  505.     LineTo(theRect.right, theRect.top   );            //    •
  506. }
  507.  
  508.  
  509. // —————————————————————————————————————————————————————————————————————————————
  510. //
  511. //    FrameBottomRightShading
  512. //
  513. // —————————————————————————————————————————————————————————————————————————————
  514. void
  515. FrameBottomRightShading(Rect theRect) 
  516. {
  517.     theRect.right--;        // Compensate for the way the rectangle hangs.
  518.     theRect.bottom--;
  519.  
  520.     MoveTo(theRect.left,  theRect.bottom);            //        •
  521.     LineTo(theRect.right, theRect.bottom);            //        •
  522.     LineTo(theRect.right, theRect.top   );            //    •••••
  523. }
  524.  
  525.  
  526. // —————————————————————————————————————————————————————————————————————————————
  527. //
  528. //    GetGlobalMappingPoint
  529. //
  530. // —————————————————————————————————————————————————————————————————————————————
  531. //        This routine returns a point that gives the horizontal and vertical
  532. //      offsets needed to map something into global coordinates.
  533. // —————————————————————————————————————————————————————————————————————————————
  534. void
  535. GetGlobalMappingPoint(WindowPeek window, Point *thePoint) 
  536. {
  537.     GrafPtr savePort;
  538.     
  539.     GetPort(&savePort);
  540.     SetPort((GrafPtr) window);
  541.     
  542.     SetPt(thePoint, 0, 0);
  543.     LocalToGlobal(thePoint);
  544.     
  545.     SetPort(savePort);
  546. }
  547.  
  548.  
  549. // —————————————————————————————————————————————————————————————————————————————
  550. //
  551. //    GetGlobalContentRect
  552. //
  553. // —————————————————————————————————————————————————————————————————————————————
  554. void 
  555. GetGlobalContentRect(WindowPeek window, Rect *contentRect) 
  556. {
  557.     Point mappingPoint;
  558.  
  559.     *contentRect = window->port.portRect;
  560.     GetGlobalMappingPoint(window, &mappingPoint);
  561.     OffsetRect(contentRect, mappingPoint.h, mappingPoint.v);
  562. }
  563.  
  564.  
  565. // —————————————————————————————————————————————————————————————————————————————
  566.